package com.cdream.basic.java8.io.aiochat;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import lombok.extern.slf4j.Slf4j;
import lombok.var;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author cdream
 * @date 2022/8/16
 */
@Slf4j
public class ChatServer {
    private static final Integer PORT = 18080;
    private static final String HOST = "localhost";
    private static final String QUIT = "QUIT";
    private static AsynchronousChannelGroup acg;
    private static AsynchronousServerSocketChannel ssc;

    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(20);

        try {
            acg = AsynchronousChannelGroup.withThreadPool(es);
            ssc = AsynchronousServerSocketChannel.open(acg);
            ssc.bind(new InetSocketAddress(PORT));
            log.info("服务端启动完成");
            while (true){
                ssc.accept(null, new AcceptsHandler());
                System.in.read();
            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IoUtil.close(ssc);
        }

    }


    public static boolean isQuit(String msg) {
        return "QUIT".equals(msg);
    }


    private static class AcceptsHandler implements CompletionHandler<AsynchronousSocketChannel, Object> {

        @Override
        public void completed(AsynchronousSocketChannel result, Object attachment) {
            if (ssc.isOpen()) {
                ssc.accept(null, this);
            }
            if (result != null && result.isOpen()) {
                ClientHandler ch = new ClientHandler(result);
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                Map<String, Object> map = MapUtil.newHashMap();
                map.put("type", "read");
                map.put("buffer", buffer);
                result.read(buffer, map, ch);
            }

        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            log.error("回调出现异常", exc);
        }
    }

    private static class ClientHandler implements CompletionHandler<Integer, Object> {
        private AsynchronousSocketChannel channel;

        public ClientHandler(AsynchronousSocketChannel channel) {
            this.channel = channel;
        }

        @Override
        public void completed(Integer result, Object attachment) {
            Map<String, Object> info = (Map<String, Object>) attachment;
            if ("read".equals(info.get("type"))) {
                ByteBuffer buffer = (ByteBuffer) info.get("buffer");
                buffer.flip();
                var msg = String.valueOf(StandardCharsets.UTF_8.decode(buffer));
                log.info("服务器收到数据：{}",msg);
                msg = msg.replace("a","b");
                info.put("type", "write");
                info.put("buffer",ByteBuffer.wrap(msg.getBytes()));
                channel.write(ByteBuffer.wrap(msg.getBytes()), info, this);
                buffer.clear();
            }
            if ("write".equals(info.get("type"))) {
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                info.put("type", "read");
                info.put("buffer", buffer);
                channel.read(buffer, info, this);
            }

        }

        @Override
        public void failed(Throwable exc, Object attachment) {

        }
    }
}
